package com.authservice.authservice.service.impl;

import ch.qos.logback.core.util.StringUtil;
import cn.hutool.core.bean.BeanUtil;
import com.authservice.authservice.domain.dto.AuthCodeDTO;
import com.authservice.authservice.domain.dto.UpdatePasswordDTO;
import com.authservice.authservice.service.AuthService;
import com.authservice.authservice.service.UserService;
import com.authservice.authservice.util.TokenUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.authservice.authservice.domain.User;
import com.commonmodule.commonmodule.util.*;
import jakarta.annotation.Resource;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

/**
 * @author zxb
 * @version 1.0
 * @date 2024-11-05 11:39
 */
@Service
public class AuthServiceImpl implements AuthService {

    @Resource
    private UserService userService;
    @Resource
    private TokenUtil tokenUtil;
    @Resource
    private RedisUtil redisUtil;

    /**
     * 账号密码登录
     * @param account 账号
     * @param password 密码
     * @return token
     */
    @Override
    public R<String> login(String account, String password) {

        // 校验手机号码格式
        if (!tokenUtil.isValidPhoneNumber(account)) {
            return R.error(500, "手机号格式不正确");
        }

        // 查询用户信息
        User user = userService.getByPhone(account);
        if (BeanUtil.isEmpty(user)) {
            return R.error(500, "无用户信息");
        }

        // 解密
        password = EncryptionUtil.decrypt(password);

        // 校验密码
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        boolean matches = passwordEncoder.matches(password, user.getPassword());
        if (!matches) {
            return R.error(500, "密码错误");
        }

        // 生成token
        String token = tokenUtil.createToken(user);
        return R.ok(token);
    }


    /**
     * 退出登录
     * @param token
     * @return
     */
    @Override
    public R<?> exit(String token) {

        try {
            // 获取key
            String key = tokenUtil.getKey(token);
            // 根据key删除缓存
            redisUtil.del(key);
            return R.ok();
        } catch (Exception e) {
            e.printStackTrace();
            return R.error();
        }
    }


    /**
     * 修改密码
     * @param updatePasswordDTO
     */
    @Override
    public R<?> updatePassword(UpdatePasswordDTO updatePasswordDTO) {

        String account = updatePasswordDTO.getAccount();
        String usedPassword = updatePasswordDTO.getUsedPassword();
        String newPassword = updatePasswordDTO.getNewPassword();

        try {
            // 解密
            usedPassword = EncryptionUtil.decrypt(usedPassword);
            newPassword = EncryptionUtil.decrypt(newPassword);

            User user = userService.getByPhone(account);
            if (BeanUtil.isEmpty(user)) {
                return R.error(500,"用户不存在");
            }

            // 校验密码
            BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
            boolean matches = passwordEncoder.matches(usedPassword, user.getPassword());
            if (!matches) {
                return R.error(500, "旧密码错误");
            }

            // 保存信息
            LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>();
            wrapper.eq(User::getId, user.getId())
                    .set(User::getPassword, passwordEncoder.encode(newPassword));
            userService.update(wrapper);

            // 删除缓存
            tokenUtil.deleteKeys(account);
            return R.ok();

        } catch (Exception e) {
            e.printStackTrace();
            return R.error();
        }

    }


    /**
     * 发送验证码
     *
     * @param phone
     * @param type 1注册  2登录  3修改密码
     * @return
     */
    @Override
    public R<?> note(String phone, Integer type) {

        // 校验手机号码格式
        if (!tokenUtil.isValidPhoneNumber(phone)) {
            return R.error(500, "手机号格式不正确");
        }

        if (type != 1) {
            // 查询用户信息
            User user = userService.getByPhone(phone);
            if (BeanUtil.isEmpty(user)) {
                return R.error(500, "无用户信息");
            }
        }


        String key = getKey(phone, type);
        if (redisUtil.verify(key)) {
            return R.ok("验证码已发送，请勿频繁操作！");
        }

        String code = AliyunUtil.note(phone);
        if (!StringUtil.isNullOrEmpty(code)) {
            redisUtil.save(key,code,2, TimeUnit.HOURS);
            return R.ok("验证码发送成功！");
        }
        return R.error(500, "发送失败！");
    }


    /**
     * 注册
     * @param authCodeDTO
     * @return
     */
    @Override
    public R<?> enroll(AuthCodeDTO authCodeDTO) {

        // 校验手机号码格式
        if (!tokenUtil.isValidPhoneNumber(authCodeDTO.getPhone())) {
            return R.error(500, "手机号格式不正确！");
        }

        // 查询用户信息
        User u = userService.getByPhone(authCodeDTO.getPhone());
        if (!BeanUtil.isEmpty(u)) {
            return R.error(500, "账号已存在！");
        }

        String key = getKey(authCodeDTO.getPhone(), 1);
        if (redisUtil.verify(key)) {
            String code = redisUtil.select(key);
            if (code.equals(authCodeDTO.getCode())) {
                User user = new User();
                user.setPhone(authCodeDTO.getPhone());
                // 解密
                String password = EncryptionUtil.decrypt(authCodeDTO.getPassword());
                BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
                user.setPassword(passwordEncoder.encode(password));
                userService.add(user);
                return R.ok("注册成功");
            } else {
                return R.error(500, "验证码不正确！");
            }
        }
        return R.error(500, "注册失败！");
    }


    /**
     * 验证码登录
     * @param authCodeDTO
     * @return
     */
    @Override
    public R<?> authCodeLogin(AuthCodeDTO authCodeDTO) {

        // 校验手机号码格式
        if (!tokenUtil.isValidPhoneNumber(authCodeDTO.getPhone())) {
            return R.error(500, "手机号格式不正确！");
        }

        String key = getKey(authCodeDTO.getPhone(), 2);
        if (redisUtil.verify(key)) {

            String code = redisUtil.select(key);
            if (code.equals(authCodeDTO.getCode())) {

                // 查询用户信息
                User user = userService.getByPhone(authCodeDTO.getPhone());
                // 生成token
                if (!BeanUtil.isEmpty(user)) {
                    String token = tokenUtil.createToken(user);

                    return R.ok(token);
                }
            } else {
                return R.error(500, "验证码不正确！");
            }
        }
        return R.error(500, "登录失败！");
    }



    /**
     * 获取key
     * @param phone
     * @param type  1注册  2登录  3修改密码
     * @return
     */
    public static String getKey(String phone, Integer type){
        if (type == 1) {
            return "enroll" + phone;
        } else if (type == 2) {
            return "login" + phone;
        } else if (type == 3) {
            return "reset" + phone;
        }
        return null;
    }

}
